package org.xteam.box2text.old;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.xteam.box2text.Frame;
import org.xteam.box2text.Point;
import org.xteam.box2text.TextStruct;

public class HOVOperator extends Operator implements IPlaceableBox {
	
	public HOVOperator(Box... boxes) {
		super(boxes);
	}

	public HOVOperator(Map<String, Integer> options, List<Box> boxes) {
		super(options, boxes);
	}
	
	public int width(Frame frame) {
		return new VOperator(options, arguments).width(frame);
	}
	
	@Override
	public List<Box> normalizeGroups(boolean splice) {
		return Arrays.asList(new Box[] { new HOVOperator(options, normalizeChildren(true)) });
	}

	public Point length(Frame frame, int context) {
		if (isEmpty()) {
			return new Point(0,0);
		}
		return hovlength(arguments, frame.getHs(options), frame);
	}

	private static Point hovlength(List<Box> arguments, int hs, Frame frame) {
		Point bp = null;
		for (Box arg : arguments) {
			if (bp == null) {
				bp = ((IPlaceableBox)arg).length(frame, OperatorKinds.H);
			} else {
				bp = hov(bp, ((IPlaceableBox)arg).length(frame, OperatorKinds.H), hs);
			}
		}
		return bp;
	}
	
	private static Point hov(Point p1, Point p2, int hs) {
		if (p2.isZero())
			return p1;
		if (p1.isZero())
			return p2;
		if (p1.height() == 0 && p2.height() == 0) {
			return new Point(p1.width() + hs + p2.width(), 0);
		}
		return new Point(p2.width(), p1.height() + p2.height());
	}
	
	/*private BoxPoint selectOperator(BoxPoint bp, Map<String, Integer> options) {
		//if (bp.height() == 0) {
			//Box b = new HOVOperator(options, bp.boxes());
			//b.setCache(bp.size());
		//	return new BoxPoint(b, bp.size());
		//}
		//Box b = new VOperator(options, bp.boxes());
		//b.setCache(bp.size());
		return new BoxPoint(b, bp.size());
	}*/

	public TextStruct place(Frame frame, TextStruct textStruct, int context) {
		if (isEmpty())
			return textStruct;
		
		if (size() == 1)
			return ((IPlaceableBox)arguments.get(0)).place(frame, textStruct, context);

		Point bp = length(frame, OperatorKinds.H);
		if (bp.height() == 0 && (frame.x() + bp.width()) <= frame.getRightMargin()) {
			return HOperator.hplace(arguments, frame.getHs(options), frame, textStruct);
		}
		Frame f = frame.setLeftMargin(frame.x());
		return VOperator.vplace(arguments, frame.getVs(options), f, textStruct);
	}

}
